﻿using System.Configuration;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Red.Controls.Utils;

namespace Red.Controls.Shell
{
    /// <summary>
    /// Base class for settings allowing to store layout related stuff and handled by the framework (thus placed in the Shell namespace).
    /// Derive your application settings from this
    /// </summary>
    public class RedSettings : ApplicationSettingsBase
    {
        #region Properties

        /// <summary>
        /// Main tool's window position and size
        /// </summary>
        [UserScopedSetting]
        [DefaultSettingValue( "" )]
        public W32.WINDOWPLACEMENT WindowPlacement
        {
            get { return GetValue<W32.WINDOWPLACEMENT>(); }
            set { SetValue( value ); }
        }

        /// <summary>
        /// If this is set to it's default value, do not load the contents of <see cref="WindowPlacement"/>
        /// </summary>
        [UserScopedSetting]
        [DefaultSettingValue( "False" )]
        public bool WindowPlacementSaved
        {
            get { return GetValue<bool>(); }
            set { SetValue( value ); }
        }

        /// <summary>
        /// Visual framework layout - drawers size, docked state, etc.
        /// This is the state that is stored and restored automatically.
        /// </summary>
        [UserScopedSetting]
        [DefaultSettingValue( "" )]
        public string WindowLayout
        {
            get { return GetValue<string>(); }
            set { SetValue( value ); }
        }

        /// <summary>
        /// Visual framework layout - drawers size, docked state, etc.
        /// This is the state that is stored and restored by the user.
        /// </summary>
        [UserScopedSetting]
        [DefaultSettingValue( "" )]
        public string UserWindowLayout
        {
            get { return GetValue<string>(); }
            set { SetValue( value ); }
        }

        /// <summary>
        /// If this flag is set to its default value of true, the framework
        /// needs to upgrade settings from a previous version
        /// </summary>
        [UserScopedSetting]
        [DefaultSettingValue( "True" )]
        public bool UpgradeRequired
        {
            get { return GetValue<bool>(); }
            set { SetValue( value ); }
        }


        #endregion Properties

        #region Interface

        /// <summary>
        /// Override this to provide logic for checking the integrity of settings data
        /// </summary>
        public virtual bool IsDataValid()
        {
            return true;
        }

        #endregion Interface

        #region Protected methods

        /// <summary>
        /// Gets the property value. 
        /// </summary>
        /// <typeparam name="T">Property type - must be given explicitily</typeparam>
        /// <param name="propName">Just omit this - it will be set automatically based on the caller property name.</param>
        /// <returns></returns>
        protected T GetValue<T>( [CallerMemberName] string propName = null )
        {
            Debug.Assert( !string.IsNullOrEmpty( propName ), "GetValue is only to be called from within a settings property" );
            return (T)( this[ propName ] );
        }

        /// <summary>
        /// Sets the property value.
        /// </summary>
        /// <typeparam name="T">Property type - will be deducted automatically base on value type</typeparam>
        /// <param name="value">Property value</param>
        /// <param name="propName">Just omit this - it will be set automatically based on the caller property name.</param>
        protected void SetValue<T>( T value, [CallerMemberName] string propName = null )
        {
            Debug.Assert( !string.IsNullOrEmpty( propName ), "SetValue is only to be called from within a settings property" );
            this[ propName ] = value;
        }

        #endregion Protected methods
    }
}
